#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <cstring>

#include "Data.h"
#include "Utils.h"

//#define DEBUG

Data::Data(string FileName)
{
	//cout << "Reading input file : " << FileName << endl;
	Vect row;

	n_ = 0;

	t_int x;
	t_uint i;

	char *sFirstLine = (char *) malloc(MAX_SIZE * sizeof(char));

	//FileName = INPUT_PATH + FileName;

	ifstream File(FileName.c_str());
	if(!File)
        {
		cerr << "Error ! Cannot read file !" << endl;
                throw "STOPPING PROG BECAUSE OF MAJOR ERROR!";
        }

	// We check how many elements there are in the first line to get the dimension :)
	// C'est plus malin quand il y aura beaucoup de données...
	stringstream ssFirstLine(stringstream::in | stringstream::out);
	File.getline(sFirstLine, MAX_SIZE);
	ssFirstLine << sFirstLine;


	i = 0;
	do
	{
		ssFirstLine >> x;       // get character from file
		#ifdef DEBUG
		cout << "[" << i << "," << n_ << "]:" << x << " ";
		#endif

		row.push_back(x);
		vect_.push_back(x);	// 1 D storage
		n_ ++;
	} while (ssFirstLine.good());

	// if there is a white spaces at the end of the 1st line
	//t_uint k = 1;
	//while (sFirstLine[strlen(sFirstLine)-k == ' ')
	{
		if (sFirstLine[strlen(sFirstLine)-1] == ' ')
		n_ --;
	//	k ++;
	}

	mat_.push_back(row);

	#ifdef DEBUG
	cout << endl;
	#endif

	File >> x;

	// Idée : Pour lire en // on pourra peut etre utiliser seekg() and seekp() :)
	// Chaque thread lira un bloc de lignes
	while(File.good())
	{
		i ++;
		for (t_uint j = 0; j < n_; j ++)
		{
			#ifdef DEBUG
			cout << "[" << i << "," << j << "]:" << x << " ";
			#endif

			row[j] = x;
			#if KADANE_VECT
			vect_.push_back(x);	// Row major 1D storage
			#endif
			File >> x;
		}
		#ifdef DEBUG
		cout << endl;
		#endif
		mat_.push_back(row);
	}

	m_ = i + 1;

	File.close();
	free(sFirstLine);
#if 0
	/* Used for column major storage in 1D array */
	for (t_uint j = 0; j < n_; j ++)
		for (i = 0; i < m_; i ++)
			vect_.push_back(mat_[i][j]);
#endif

	// Only if BAE is used !
#if BAE
	t_uint rows = m_;
	t_uint columns = n_;
	mat_transpose_.resize(columns);
	for (t_uint col = 0 ; col < columns ; col++)
	{
		mat_transpose_[col].resize(rows);
		for (t_uint row = 0 ; row < rows ; row++)
		{
			mat_transpose_[col][row] = mat_[row][col];
		}
	}
#endif
}



Data::~Data()
{


}

t_uint Data::getRows() const
{
	//we should replace this to get rid off rows and columns
	return m_;
	//return rows;
}
t_uint Data::getColumns() const
{
	//we should replace this to get rid off rows and columns
	return n_;
	//return columns;
}

t_uint Data::getM() const
{
	return m_;
}

t_uint Data::getN() const
{
	return n_;
}

const Mat& Data::getMat() const
{
	return mat_;
}

const Mat& Data::getMatTranspose() const
{
	return mat_transpose_;
}

const Vect& Data::getVect() const
{
	return vect_;
}


void Data::dispMat()
{
	for (t_uint i = 0; i < getM(); i ++)
	{
		for (t_uint j = 0; j < getN(); j ++)
		{
			cout << mat_[i][j] << "\t";
		}
		cout << endl;
	}
}

void Data::dispVect()
{
	for (t_uint i = 0; i < getM(); i ++)
	{
		for (t_uint j = 0; j < getN(); j ++)
		{
			cout << GetRowMajor(i, j) << " ";
		}
		cout << endl;
	}
}
